package com.andnnl.guava;

import com.google.common.util.concurrent.*;

import java.util.List;
import java.util.concurrent.Executors;

/**
 * 多个任务异步同时执行，有一个错的，返回错，全部成功才返回成功
 * 或者有成功的返回成功数量
 * Created by chenss on 2019/9/20.
 */
public class FutureTest2 {


    public static void main(String[] args) {

        // 创建线程池
        ListeningExecutorService listeningExecutorService = MoreExecutors.
                listeningDecorator(Executors.newFixedThreadPool(10));
//        FutureCallBackTask callback = new FutureCallBackTask();
        long start = System.currentTimeMillis();

        // 任务1
        ListenableFuture<Integer> future1 = listeningExecutorService.submit(() -> {
            System.out.printf("开始调用第1个future%n");
            Thread.sleep(2000);
            System.out.printf("调用第1个future，执行时间是%d%n", System.currentTimeMillis());
//            throw new RuntimeException("任务1出现了异常");
            return 1;
        });

        // 任务2
        ListenableFuture<Integer> future2 = listeningExecutorService.submit(() -> {
            System.out.printf("开始调用第2个future%n");
            Thread.sleep(3000);
            System.out.printf("调用第2个future，执行时间是%d%n", System.currentTimeMillis());
//            throw new RuntimeException("任务2出现了异常");
            return 2;
        });

        //对多个ListenableFuture的合并，返回一个当所有Future成功时返回多个Future返回值组成的List对象。
//        allAsList：对多个ListenableFuture的合并，返回一个当所有Future成功时返回多个Future返回值组成的List对象。注：当其中一个Future失败或者取消的时候，将会进入失败或者取消。
//        successfulAsList：和allAsList相似，唯一差别是对于失败或取消的Future返回值用null代替。不会进入失败或者取消流程。
        // 注：当其中一个Future失败或者取消的时候，将会进入失败或者取消。
        final ListenableFuture<List<Integer>> allFutures = Futures.allAsList(future1, future2);
//        final ListenableFuture<List<Integer>> allFutures = Futures.successfulAsList(future1, future2);

        //对于多个ListenableFuture的进行转换，返回一个新的ListenableFuture
        //transformAsync
        //transform
        final ListenableFuture<String> transform = Futures.transform(allFutures, new AsyncFunction<List<Integer>, String>() {
//        final ListenableFuture<String> transform = Futures.transformAsync(allFutures, new AsyncFunction<List<Integer>, String>() {
            /**
             * 用给定的输入封装一个特定的ListenableFuture作为输出
             *
             * @param input
             */
            @Override
            public ListenableFuture<String> apply(List<Integer> input) {
                System.out.println(allFutures);
                System.out.println("input:" + input);
                // 立即返回一个待返回值的ListenableFuture
                // 这里可以对input进行复杂的处理，返回最终的一个结果  比如：对团单详情，团单优惠，团单使用范围进行组装
                return Futures.immediateFuture(String.format("执行成功的任务的数量是:%d", input.stream().filter(a -> a != null).toArray().length));
            }
        }, listeningExecutorService);

        // 注册回调事件
        Futures.addCallback(transform, new FutureCallback<Object>() {

            public void onSuccess(Object result) {
                System.out.println("进入正确的回调函数");
                System.out.printf("任务执行的结果是：%s%n", result);
            }

            public void onFailure(Throwable thrown) {
                System.out.println("进入错误的回调函数");
                System.out.printf("系统出错了，错误原因是：%s%n", thrown.getMessage());
            }
        }, listeningExecutorService);

        long end = System.currentTimeMillis();
        System.out.printf("接口总耗时%d毫秒%n", end - start);

    }

}
